
cbuffer cbPerObject
{
	float4x4 gWVP;
	float4x4 gWorld;
	float4 gDiffMat;
	float4 gSpecMat;
};

cbuffer cbPerFrame
{
	float3 gDiffLight;
	float3 gAmbLight;
	float3 gSpecLight;
	float3 gLightPosW;
	float3 gEyePosW;
};


Texture2D gDiffuseMap;
Texture2D gNormalMap;

SamplerState gTriLinearSam
{
	Filter = MIN_MAG_MIP_LINEAR;
	AddressU = Wrap;
	AddressV = Wrap;
	MaxAnisotropy = 4;
};

struct VS_IN
{
	float3 posL     : POSITION;
	float3 tangentL : TANGENT;
	float3 normalL  : NORMAL;
	float2 texC     : TEXCOORD;
};

struct VS_OUT
{
	float4 posH         : SV_POSITION;
	float3 posW         : TEXCOORD0;
	float3 normalW      : TEXCOORD1;
	float3 tangentW     : TEXCOORD2;
    float2 texC         : TEXCOORD3;
};

VS_OUT VS(VS_IN vIn)
{
	VS_OUT vOut;
	
	vOut.posH = mul(float4(vIn.posL, 1.0f), gWVP);
	vOut.posW = mul(float4(vIn.posL, 1.0f), gWorld).xyz;
	
	float3 normalW = mul(float4(vIn.normalL, 0.0f), gWorld).xyz;
	vOut.normalW = normalize(normalW);
	
	float3 tangentW = mul(float4(vIn.tangentL, 0.0f), gWorld).xyz;
	vOut.tangentW = normalize(tangentW);

	vOut.texC = vIn.texC;
	
	return vOut;
}

float4 PS2(VS_OUT pIn) : SV_Target
{
	return float4(1,1,1,1);
}

float4 PS(VS_OUT pIn) : SV_Target
{      
	float3 normalW = normalize(pIn.normalW);
	float3 n = normalW;
	float3 tangentW = normalize(pIn.tangentW);
	
	float3 bitangentW = normalize(cross(normalW, tangentW));
	
	float3x3 tangentToWorld = float3x3(tangentW, bitangentW, normalW);
	
	float3 newNormalT = 2 * (gNormalMap.Sample(gTriLinearSam, pIn.texC).xyz - 0.5f);
	normalW = mul(float4(newNormalT, 0.0f), tangentToWorld);
	

	float3 lightVecW = normalize(gLightPosW - pIn.posW);
	float3 vertToEyeW = normalize(gEyePosW - pIn.posW);
	
	
  
	float3 ambient = gDiffMat * gAmbLight;
	
	
  
	float diffLightIntensity = max(dot(normalW, lightVecW), 0);
	float3 diffuse = diffLightIntensity * gDiffMat * gDiffLight;
  
	float3 reflW = reflect(normalize(-lightVecW), normalW);
	float specLightIntensity = pow(max(dot(reflW, vertToEyeW), 0.0f), gSpecMat.w);
	float3 specular = specLightIntensity * gSpecMat * gSpecLight;
	
	if(dot(n, lightVecW) <= 0)
	{
		specular = 0;
		//diffuse = 0;
		}
  
	return float4( (ambient + diffuse) * gDiffuseMap.Sample(gTriLinearSam, pIn.texC) + specular, gDiffMat.w);
}

BlendState AdditiveBlending
{
    AlphaToCoverageEnable = FALSE;
    BlendEnable[0] = TRUE;
    SrcBlend = ONE;
    DestBlend = ONE;
    BlendOp = ADD;
    SrcBlendAlpha = ZERO;
    DestBlendAlpha = ZERO;
    BlendOpAlpha = ADD;
    RenderTargetWriteMask[0] = 0x0F;
};

DepthStencilState RenderNonShadows
{
    DepthEnable = true;
    DepthWriteMask = ZERO;
    DepthFunc = Less_Equal;
    
    StencilEnable = true;
    StencilReadMask = 0xFFFFFFFF;
    StencilWriteMask = 0x0;
    
    FrontFaceStencilFunc = Equal;
    FrontFaceStencilPass = Keep;
    FrontFaceStencilFail = Zero;
    
    BackFaceStencilFunc = Never;
    BackFaceStencilPass = Zero;
    BackFaceStencilFail = Zero;
};

technique10 tech
{
    pass P0
    {
        SetVertexShader( CompileShader( vs_4_0, VS() ) );
        SetGeometryShader( NULL );
        SetPixelShader( CompileShader( ps_4_0, PS() ) );
		//SetBlendState( NoBlending, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
        //SetDepthStencilState( RenderNonShadows, 0 ); //state, stencilref
        //SetRasterizerState( EnableCulling );
    }
}
